package com.example.sample.vpn;

import android.content.Intent;
import android.net.VpnService;
import android.os.ParcelFileDescriptor;
import android.util.Log;

import net.liteheaven.xblib.common.rom.ApkUtil;

import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.InetSocketAddress;
import java.nio.channels.DatagramChannel;

public class MyVpnService extends VpnService {

    private static final String TAG = "MyVpnService";
    private Thread mTunThread;
    private ParcelFileDescriptor mInterface;
    private Builder mBuilder = new Builder();

    private static MyVpnService mInstance = null;
    public static MyVpnService getInstance(){
        return mInstance;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "onStartCommand");

        // 启动VPN线程
        startTunThread();

        //String apk = "com.example.sample";
        String apk = "sh.lilith.dgame.mi";
        int pid = ApkUtil.getProcessId(getApplicationContext(), "com.example.sample");
        String path = "/proc/"+pid+"/net/"+"tcp";
        //addWatch(path);
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "onDestroy");
        mInstance = null;
    }

    private void startTunThread(){
        final Runnable r = new Runnable() {
            @Override
            public void run() {
                try {
                    //a. Configure the TUN and get the interface.
                    mBuilder.setSession("MyVPNService");

                    //mBuilder.addAddress("180.97.33.107", 24);
                    mBuilder.addAddress("10.0.8.1", 24);
                    //mBuilder.addAddress("198.51.100.10", 32);

                    //mBuilder.addRoute("180.97.33.0", 24);
                    //mBuilder.addRoute("0.0.0.0", 0);
                    mBuilder.addRoute("192.168.31.228", 32);
                    mBuilder.addRoute("111.111.111.111", 32);
                    mBuilder.setConfigureIntent(null);

                    //mBuilder.addDnsServer
                    // ("8.8.8.8");
                    mInterface = mBuilder.establish();

                    //b. Packets to be sent are queued in this input stream.
                    FileInputStream in = new FileInputStream(
                            mInterface.getFileDescriptor());

                    //b. Packets received need to be written to this output stream.
                    FileOutputStream out = new FileOutputStream(
                            mInterface.getFileDescriptor());

                    //c. The UDP channel can be used to pass/get ip package to/from server
                    DatagramChannel tunnel = DatagramChannel.open();
                    // Connect to the server, localhost is used for demonstration only.
                    tunnel.connect(new InetSocketAddress("127.0.0.1", 8087));

                    //d. Protect this socket, so package send by it will not be feedback to the vpn service.
                    protect(tunnel.socket());

                    //e. Use a loop to pass packets.
                    while (true) {
                        //get packet with in
                        //put packet to tunnel
                        //get packet form tunnel
                        //return packet with out
                        //sleep is a must

                        FileDescriptor fd = mInterface.getFileDescriptor();
                        VpnNative.parase(fd);

                        Thread.sleep(1);
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (mInterface != null) {
                            mInterface.close();
                            mInterface = null;
                        }
                    } catch (Exception e) {
                        // ignore
                    }
                }
            }
        };
        if (mTunThread == null){
            mTunThread = new Thread(r);
            mTunThread.start();
        }
    }


}
